﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Data;
using StyleMVVM.DependencyInjection;
using StyleMVVM.Utilities;
using StyleMVVM.View;
#if !DOT_NET
using Windows.Foundation.Collections;
#endif
#if NETFX_CORE
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

#else
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

#endif

namespace StyleMVVM.ViewModel
{
	/// <summary>
	/// This is the default implementation for ViewModels associated with a Page
	/// </summary>
	public class PageViewModel : NavigatingViewModel, IViewAware, ILoadedAwareViewModel
	{
		private WeakReference<FrameworkElement> viewReference;
		private INavigationService navigation;
		private bool foundFrame = false;

		#region Navigation

		public INavigationService Navigation
		{
			get
			{
				if (navigation == null || !navigation.IsValid || !foundFrame)
				{
					Frame frame = GetFrame();

					if (frame != null)
					{
						foundFrame = true;

						navigation = Container.Locate<INavigationService>(frame);
					}
					else
					{
						navigation = Container.Locate<INavigationService>(ContainerHelper.SingleNull);
					}
				}

				return navigation;
			}
		}

		public FrameworkElement View
		{
			get
			{
				FrameworkElement view = null;

				if (viewReference != null)
				{
					viewReference.TryGetTarget(out view);
				}

				return view;
			}
			set
			{
				FrameworkElement oldView = null;

				if (viewReference != null)
				{
					viewReference.TryGetTarget(out oldView);
				}

				if (oldView != value)
				{
					if (value != null)
					{
						viewReference = new WeakReference<FrameworkElement>(value);
					}

					else
					{
						viewReference = null;
					}

					navigation = null;
				}
			}
		}

		private Frame GetFrame()
		{
			DependencyObject tempFrame = View;

			while (tempFrame != null && !(tempFrame is Frame))
			{
				tempFrame = VisualTreeHelper.GetParent(tempFrame) as FrameworkElement;
			}

			return tempFrame as Frame;
		}

		#endregion

		public virtual void OnLoaded(object sender, RoutedEventArgs args)
		{
			OnPropertyChanged("Navigation");
		}

		public virtual void OnUnloaded(object sender, RoutedEventArgs args)
		{
		}
	}
}